home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CD ROM Paradise Collection 4
/
CD ROM Paradise Collection 4 1995 Nov.iso
/
clang
/
text_eng.zip
/
WATCOM
/
TEXTURE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-07-01
|
35KB
|
1,151 lines
/*
* TEXTURE.C Version 1.0a by Lee Lorenz llorenz@delphi.com
* *WATCOM VERSION*
* First, Please excuse this mess.
*
* Next, Welcome to high-speed image processing... My desire was to
* rotate/scale a bitmap in real-time, and this was the result.
* There were plenty of "examples" of texture mapping, in obfuscated
* highly optimized assembly, but even the "C" and Pascal examples left
* alot to be desired; after all, I wanted to have more freedom to display
* images, and didn't want to bother with the trigonometry. With the simple
* idea of "shooting" a line (Bresenham-style) through a source bitmap, I
* developed this technique contained in DrawTexture. It may not be original,
* but I haven't seen it used anywhere else. It can even be augmented with
* anti-aliasing for image processing. I release this program and technique
* into the public domain, and I hope to create a highly optimized 386
* assembler version for my personal library. Please try to credit me when
* possible, if this shows you anything new or interesting, and you use it
* in any distributed program (Freeware/shareware/commercial).
*
* What this program does:
* Draws a bitmap into any 4-sided polygon. First vector is upper-left
* second is upper-right, third is lower-right, and last is lower-left.
*
* Limitations:
* Don't try to use a "Horizontally convex" polygon.
* Undefined results with intersected polygons
*
* What remains to be done:
* 1. A good intersection-detection routine.
* 2. A quick 2-D rotation/scaling transform for the corners. I want to
* be able to "spin" the bitmap/sprite about a point.
* 3. Possible, slower alternative to scan "horizontal convex" polygons
* and intersected polygons
*
*/
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include <bios.h>
#include <dos.h>
#include "gl.h"
#include <time.h>
int YZSize;
unsigned char ibuff[65000],ipal[768];
struct
{
char filename[80];
int sizex;
int sizey;
unsigned char *buff;
unsigned char *pal;
} slots[64];
struct text_s
{
unsigned char *Buffer;
int XSize,YSize;
} MyMap;
struct quad_s
{
int x[4],y[4];
} MyPoly;
void DrawTexture(struct quad_s *poly,struct text_s *Texture,int debug);
void OrderPoly(struct quad_s *poly,unsigned char *order);
/* This routine eliminates intersections by swapping corners
* if an intersection exists...
* "adjacent" segments, by nature, cannot intersect, therefore we only
* need to check opposite segments (AB,CD & DA,BC)
* Actually, in retrospect, the poly cannot have "horizontal convexity"
* That is, the scan algorithm cannot handle more than one chunk, Our
* test, there for is for opposite corners _NOT_ to be next to one another
* when ordered...
*/
void UnIntersectQuad(struct quad_s *poly)
{
unsigned char work_order[4];
int i;
OrderPoly(poly,work_order);
/* Top Convexity/intersection */
switch(work_order[0])
{
case 0: /* Test to insure 2 is not adjacent */
if(work_order[1]==2)
{
/* Swap 1 and 2 */
i=poly->x[1];
poly->x[1]=poly->x[2];
poly->x[2]=i;
i=poly->y[1];
poly->y[1]=poly->y[2];
poly->y[2]=i;
}
break;
case 1: /* Test to insure 3 is not adjacent */
if(work_order[1]==3)
{
/* Swap 0 and 3 */
i=poly->x[0];
poly->x[0]=poly->x[3];
poly->x[3]=i;
i=poly->y[0];
poly->y[0]=poly->y[3];
poly->y[3]=i;
}
break;
case 2: /* Test to insure 0 is not adjacent */
if(work_order[1]==0)
{
/* Swap 1 and 2 */
i=poly->x[1];
poly->x[1]=poly->x[2];
poly->x[2]=i;
i=poly->y[1];
poly->y[1]=poly->y[2];
poly->y[2]=i;
}
break;
case 3: /* Test to insure 1 is not adjacent */
if(work_order[1]==1)
{
/* Swap 0 and 3 */
i=poly->x[0];
poly->x[0]=poly->x[3];
poly->x[3]=i;
i=poly->y[0];
poly->y[0]=poly->y[3];
poly->y[3]=i;
}
break;
}
OrderPoly(poly,work_order);
/* BOTTOM Convexity/intersection */
switch(work_order[3])
{
case 0: /* Test to insure 2 is not adjacent */
if(work_order[2]==2)
{
/* Swap 1 and 2 */
i=poly->x[1];
poly->x[1]=poly->x[2];
poly->x[2]=i;
i=poly->y[1];
poly->y[1]=poly->y[2];
poly->y[2]=i;
}
break;
case 1: /* Test to insure 3 is not adjacent */
if(work_order[2]==3)
{
/* Swap 0 and 3 */
i=poly->x[0];
poly->x[0]=poly->x[3];
poly->x[3]=i;
i=poly->y[0];
poly->y[0]=poly->y[3];
poly->y[3]=i;
}
break;
case 2: /* Test to insure 0 is not adjacent */
if(work_order[2]==0)
{
/* Swap 1 and 2 */
i=poly->x[1];
poly->x[1]=poly->x[2];
poly->x[2]=i;
i=poly->y[1];
poly->y[1]=poly->y[2];
poly->y[2]=i;
}
break;
case 3: /* Test to insure 1 is not adjacent */
if(work_order[2]==1)
{
/* Swap 0 and 3 */
i=poly->x[0];
poly->x[0]=poly->x[3];
poly->x[3]=i;
i=poly->y[0];
poly->y[0]=poly->y[3];
poly->y[3]=i;
}
break;
}
/* Now for intersection test... */
}
int LoadSlot(int sl,char *fname);
void setcolor(unsigned char c,unsigned char r,unsigned char g,unsigned char b);
int lastlength,lastdelta;
unsigned char *ScreenPtr;
struct Pal_s
{
unsigned char Red;
unsigned char Blue;
unsigned char Green;
};
/*
This algorithm is based on the calculation of the third side of a triangle
given the known two sides are connected by a right angle.
This formula is: a^2+b^2=c^2. a and b are the absolute X-Y deltas.
The first calcluation of c then becomes a, and Z delta becomes b,
and we do it again. While we _HAVE_ to calculate the squares, it is not needed
to calc the roots.
i.e. Deltas of 1+1+5=7, 1+2+4=7, but distance is less on second...
27 21
Thus, we simply add the squares of all of the absolute deltas.
*/
int FindBestMatch(struct Pal_s *Pal,int r,int g,int b)
{
int Distance,i,j,k,R,G,B;
k=12288; j=0;
for(i=0;i<256;i++)
{
R=abs(Pal[i].Red-r);
R*=R;
G=abs(Pal[i].Green-g);
G*=G;
B=abs(Pal[i].Blue-b);
B*=B;
Distance=R+G+B;
if(Distance<k)
{
j=i; k=Distance;
}
}
return(j);
}
/*
A simple routine to draw a four-sided polygon in a given color.
*/
void DrawPoly(struct quad_s *Poly,int c)
{
GL_Line(Poly->x[0],Poly->y[0],Poly->x[1],Poly->y[1],c);
GL_Line(Poly->x[1],Poly->y[1],Poly->x[2],Poly->y[2],c);
GL_Line(Poly->x[2],Poly->y[2],Poly->x[3],Poly->y[3],c);
GL_Line(Poly->x[3],Poly->y[3],Poly->x[0],Poly->y[0],c);
GL_SetPixel(Poly->x[0],Poly->y[0],c);
}
unsigned char Order[4];
int WhiteColor,RedColor,BlackColor,GrayColor;
int rcount,lcount,rva[8],rvb[8],lva[8],lvb[8],rcnt[8],lcnt[8];
#define ROTATIONS 30
/* I wish DJGPP had a decent random macro!!!!
* I'll get a 32-bit version done soon
*/
#define RAND(x) (rand()%x)
int NewDir(int x,int y,int olddir);
int UpdateX(int x,int direction);
int UpdateY(int y,int direction);
void main(void)
{
long DeltaX,DeltaY,XSize,YSize;
int i,j,k,NewY;
/* GrContext ScrCtx; */
unsigned char *RPtr;
unsigned char *BuffPtr;
for(i=0;i<64;i++)
{
slots[i].filename[0]=0;
slots[i].pal=NULL;
slots[i].buff=NULL;
slots[i].sizex=0;
slots[i].sizey=0;
}
GL_InitMode13();
slots[0].buff=ibuff;
slots[0].pal=ipal;
GL_Gif("bnbtitle.gif",slots[0].buff,slots[0].pal,&slots[0].sizex,&slots[0].sizey);
/* LoadSlot(0,"bnbtitle.gif"); */
MyMap.Buffer=slots[0].buff;
MyMap.XSize=slots[0].sizex;
MyMap.YSize=slots[0].sizey;
for(i=0;i<256;i++)
{
/* slots[0].pal[i*3]/=4;
slots[0].pal[(i*3)+1]/=4;
slots[0].pal[(i*3)+2]/=4; */
setcolor(i,
slots[0].pal[i*3],
slots[0].pal[(i*3)+1],
slots[0].pal[(i*3)+2]);
}
WhiteColor=FindBestMatch((struct Pal_s *)slots[0].pal,63,63,63);
RedColor=FindBestMatch((struct Pal_s *)slots[0].pal,63,13,13);
BlackColor=FindBestMatch((struct Pal_s *)slots[0].pal,0,0,0);
GrayColor=FindBestMatch((struct Pal_s *)slots[0].pal,30,30,30);
/* GrSaveContext(&ScrCtx); */
ScreenPtr=(unsigned char *)0x0a0000; /* ScrCtx.gc_baseaddr; */
RPtr=ScreenPtr;
XSize=slots[0].sizex*65536;
YSize=slots[0].sizey*65536;
DeltaX=XSize/320;
DeltaY=YSize/200;
j=0;
DeltaX=XSize/(320);
RPtr=ScreenPtr;
j=0;
memset(RPtr,0,320*200);
DeltaX=XSize/320;
RPtr=ScreenPtr;
memset(ScreenPtr,BlackColor,320*200);
MyPoly.x[0]=320/10;
MyPoly.x[1]=320-(320/15);
MyPoly.x[2]=320-(320/5);
MyPoly.x[3]=320/12;
MyPoly.y[0]=200/20;
MyPoly.y[1]=200/10;
MyPoly.y[2]=200-(200/15);
MyPoly.y[3]=200-(200/25);
DrawPoly(&MyPoly,WhiteColor);
DrawTexture(&MyPoly,&MyMap,0);
while(!kbhit())
{
rand();
for(i=0;i<ROTATIONS;i++)
{
rand();
if(kbhit())
break;
MyPoly.x[0]=(319*(i+1))/ROTATIONS;
MyPoly.x[1]=319;
MyPoly.x[2]=319-(319*(i+1))/ROTATIONS;
MyPoly.x[3]=0;
MyPoly.y[0]=0;
MyPoly.y[1]=(199*(i+1))/ROTATIONS;
MyPoly.y[2]=199;
MyPoly.y[3]=199-(199*(i+1))/ROTATIONS;
DrawPoly(&MyPoly,RedColor);
DrawTexture(&MyPoly,&MyMap,0);
}
for(i=0;i<ROTATIONS;i++)
{
rand();
if(kbhit())
break;
MyPoly.x[3]=(319*(i+1))/ROTATIONS;
MyPoly.x[0]=319;
MyPoly.x[1]=319-(319*(i+1))/ROTATIONS;
MyPoly.x[2]=0;
MyPoly.y[3]=0;
MyPoly.y[0]=(199*(i+1))/ROTATIONS;
MyPoly.y[1]=199;
MyPoly.y[2]=199-(199*(i+1))/ROTATIONS;
DrawPoly(&MyPoly,WhiteColor);
DrawTexture(&MyPoly,&MyMap,0);
}
for(i=0;i<ROTATIONS;i++)
{
rand();
if(kbhit())
break;
MyPoly.x[2]=(319*(i+1))/ROTATIONS;
MyPoly.x[3]=319;
MyPoly.x[0]=319-(319*(i+1))/ROTATIONS;
MyPoly.x[1]=0;
MyPoly.y[2]=0;
MyPoly.y[3]=(199*(i+1))/ROTATIONS;
MyPoly.y[0]=199;
MyPoly.y[1]=199-(199*(i+1))/ROTATIONS;
DrawPoly(&MyPoly,RedColor);
DrawTexture(&MyPoly,&MyMap,0);
}
for(i=0;i<ROTATIONS;i++)
{
rand();
if(kbhit())
break;
MyPoly.x[1]=(319*(i+1))/ROTATIONS;
MyPoly.x[2]=319;
MyPoly.x[3]=319-(319*(i+1))/ROTATIONS;
MyPoly.x[0]=0;
MyPoly.y[1]=0;
MyPoly.y[2]=(199*(i+1))/ROTATIONS;
MyPoly.y[3]=199;
MyPoly.y[0]=199-(199*(i+1))/ROTATIONS;
DrawPoly(&MyPoly,WhiteColor);
DrawTexture(&MyPoly,&MyMap,0);
}
}
while(kbhit())
getch();
while(!kbhit())
{
rand();
for(i=0;i<20;i++)
{
rand();
if(kbhit())
break;
MyPoly.x[0]=0-(i*8);
MyPoly.x[1]=319+(i*8);
MyPoly.x[2]=319+(i*8);
MyPoly.x[3]=0-(i*8);
MyPoly.y[0]=0-(i*8);
MyPoly.y[1]=0-(i*8);
MyPoly.y[2]=199+(i*8);
MyPoly.y[3]=199+(i*8);
/* DrawPoly(&MyPoly,RedColor); */
DrawTexture(&MyPoly,&MyMap,0);
}
for(i=20;i;i--)
{
rand();
if(kbhit())
break;
MyPoly.x[0]=0-(i*8);
MyPoly.x[1]=319+(i*8);
MyPoly.x[2]=319+(i*8);
MyPoly.x[3]=0-(i*8);
MyPoly.y[0]=0-(i*8);
MyPoly.y[1]=0-(i*8);
MyPoly.y[2]=199+(i*8);
MyPoly.y[3]=199+(i*8);
/* DrawPoly(&MyPoly,RedColor); */
DrawTexture(&MyPoly,&MyMap,0);
}
}
while(kbhit())
getch();
i=1;
j=2;
k=3;
NewY=0; /* Directions of points */
while(!kbhit())
{
MyPoly.x[0]=UpdateX(MyPoly.x[0],i);
MyPoly.y[0]=UpdateY(MyPoly.y[0],i);
i=NewDir(MyPoly.x[0],MyPoly.y[0],i);
MyPoly.x[1]=UpdateX(MyPoly.x[1],j);
MyPoly.y[1]=UpdateY(MyPoly.y[1],j);
j=NewDir(MyPoly.x[1],MyPoly.y[1],j);
MyPoly.x[2]=UpdateX(MyPoly.x[2],k);
MyPoly.y[2]=UpdateY(MyPoly.y[2],k);
k=NewDir(MyPoly.x[2],MyPoly.y[2],k);
MyPoly.x[3]=UpdateX(MyPoly.x[3],NewY);
MyPoly.y[3]=UpdateY(MyPoly.y[3],NewY);
NewY=NewDir(MyPoly.x[3],MyPoly.y[3],NewY);
/* memset(RPtr,0,320*200); */
UnIntersectQuad(&MyPoly);
DrawTexture(&MyPoly,&MyMap,0);
}
while(kbhit())
getch();
getch();
GL_TextMode();
/* GrSetMode(GR_default_text); */
}
/*
* Convenience function... update the direction, if needed
*/
int NewDir(int x,int y,int olddir)
{
if(x<=0)
{
if(y<=0)
{
return(3);
}
else
{
if(y>=199)
{
return(1);
}
return(RAND(3)+1);
}
}
else
{
if(x>=319)
{
if(y<=0)
{
return(5);
}
else
{
if(y>=199)
{
return(7);
}
return(RAND(3)+5);
}
}
else
{
if(y<=0)
{
return(RAND(3)+3);
}
else
{
if(y>=199)
{
olddir=RAND(3); if(olddir==2) olddir=7;
return(olddir);
}
return(olddir);
}
}
}
}
/*
* Convenience function... update the X-Co-ord given a direction
*/
int UpdateX(int x,int direction)
{
switch(direction)
{
case 0: /* UP */
case 4:
return(x);
break;
case 1: /* UP-RIGHT */
case 2:
case 3:
return(x+1);
break;
case 5:
case 6:
case 7:
return(x-1);
break;
}
return(x);
}
/*
* Convenience function... update the Y-Co-ord given a direction
*/
int UpdateY(int y,int direction)
{
switch(direction)
{
case 2:
case 6:
return(y);
break;
case 0: /* UP */
case 1: /* UP-RIGHT */
case 7:
return(y-1);
break;
case 3:
case 4:
case 5:
return(y+1);
break;
}
return(y);
}
void disable(void);
void enable(void);
#pragma aux disable = "cli"
#pragma aux enable = "sti"
/*
* Program the RAMDAC 256-color palette. Seems like I'm _ALWAYS_ re-inventing
* this one!
*/
void setcolor(unsigned char c,unsigned char r,unsigned char g,unsigned char b)
{
disable();
outp(0x3c8,c);
inp(0x80);
outp(0x3c9,r);
inp(0x80);
outp(0x3c9,g);
inp(0x80);
outp(0x3c9,b);
enable();
}
/*
* Return an array of vector IDs sorted by Y value
*/
void OrderPoly(struct quad_s *poly,unsigned char *order)
{
int i,j,x,y;
for(i=0;i<4;i++)
{
order[i]=(unsigned char)i;
}
for(i=0;i<3;i++)
{
for(j=(i+1);j<4;j++)
{
if(poly->y[order[j]]<poly->y[order[i]])
{
x=order[i]; order[i]=order[j]; order[j]=x;
}
}
}
}
/*
* General purpose linear conversion routine
* I use a more complex version at work that reduces precision to prevent
* overflows.
*/
long lconvert(long a,long b,long c)
{
if(b)
{
return((a*c)/b);
}
return(0);
}
/*
* Return an arbitrary X point on a given line
*/
int XPoint(int x1,int y1,int x2,int y2,int ny)
{
int z;
x2-=x1;
y2-=y1;
ny-=y1;
z=lconvert(x2,y2,ny);
return(z+x1);
}
/*
* Return an arbitrary Y point on a given line
*/
int YPoint(int x1,int y1,int x2,int y2,int nx)
{
int z;
x2-=x1;
y2-=y1;
nx-=x1;
z=lconvert(y2,x2,nx);
return(z+y1);
}
/*
* Returns a floating point version of a 16.16 signed fixed point number
*/
float fixed2float(long z)
{
int sign;
unsigned long whole,fraction;
float result;
sign=0;
if(z<0)
{
sign=1;
z=0-z;
}
whole=z>>16;
fraction=z&0x0ffff;
result=(float)(fraction); result/=65536.0;
result+=(float)(whole);
if(sign) result=0.0-result;
return(result);
}
/*
* What we do, is for each Screen Y, we draw a line of texture
*
*
* This routine cannot handle "horizontal convexity", that is, when we
* get two chunks to draw on the same scan line. The program will freak out,
* so "UnIntersectQuad" is used to "remove" the convexity... normally, you
* would just avoid this situation. Likewise, the routine doesn't like
* intersections too much, but surprisingly, the program won't blow any
* serious chunks, as long as the convexity is taken care of. Images can
* be flipped, by re-ordering the corners of your polygon.
* Polygon Co-ordinates can range from -32768 to 32767, as I use SIGNED
* 16.16bit fixed point numbers.
*
*
*/
void DrawTexture(struct quad_s *poly,struct text_s *Texture,int debug)
{
long i,j,k,ysize;
long LeftVectorA,LeftVectorB,RightVectorA,RightVectorB;
long YCheck,LeftSegment,RightSegment,m,n,o,p,q,OSize;
long LeftDelta,LeftStartX,RightDelta;
long L_Size,R_Size,LeftBDeltaX,LeftBDeltaY;
long RightBDeltaX,RightBDeltaY,RightXPos,RightYPos;
long LeftXPos,LeftYPos,LeftCount,RightCount,LeftX,RightX;
unsigned char *screenptr;
lcount=rcount=1;
OrderPoly(poly,Order); /* Order now holds points from top to bottom */
ysize=poly->y[Order[3]]-poly->y[Order[0]]; /* Total screen Y Size */
YZSize=ysize;
if(ysize<3) /* Don't even try if too small */
return;
YCheck=poly->y[Order[3]]; /* 'Lowest' Y+some amount */
/* Now, load data for first two segments... */
screenptr=ScreenPtr;
i=320*poly->y[Order[0]];
screenptr+=i;
i=0; j=0; k=0;
m=(Order[0]+1)%4; n=(Order[0]+3)%4;
while(i==j && k<3)
{
YCheck+=20;
i=XPoint(poly->x[Order[0]],poly->y[Order[0]],
poly->x[m],poly->y[m],YCheck);
j=XPoint(poly->x[Order[0]],poly->y[Order[0]],
poly->x[n],poly->y[n],YCheck);
k++;
}
if(k==3)
{
/* Either, invalid, or flat line! */
i=poly->x[m]; j=poly->x[n];
if(i==j)
return; /* Invalid polygon... */
}
LeftVectorA=Order[0];
RightVectorA=Order[0];
if(i<j) /* 0,m is LEFT edge */
{
LeftVectorB=m; RightVectorB=n;
LeftCount=poly->y[LeftVectorB]-poly->y[LeftVectorA];
RightCount=poly->y[RightVectorB]-poly->y[RightVectorA];
L_Size=LeftCount;
R_Size=RightCount;
i=poly->x[LeftVectorB]-poly->x[LeftVectorA];
LeftDelta=lconvert(i,LeftCount,65536);
j=poly->x[RightVectorB]-poly->x[RightVectorA];
RightDelta=lconvert(j,RightCount,65536);
LeftX=poly->x[LeftVectorA]*65536;
RightX=LeftX;
}
else
{
LeftVectorB=n; RightVectorB=m;
LeftCount=poly->y[LeftVectorB]-poly->y[LeftVectorA];
RightCount=poly->y[RightVectorB]-poly->y[RightVectorA];
L_Size=LeftCount;
R_Size=RightCount;
i=poly->x[LeftVectorB]-poly->x[LeftVectorA];
LeftDelta=lconvert(i,LeftCount,65536);
j=poly->x[RightVectorB]-poly->x[RightVectorA];
RightDelta=lconvert(j,RightCount,65536);
LeftX=poly->x[LeftVectorA]*65536;
RightX=LeftX;
}
switch((LeftVectorA<<2)|LeftVectorB)
{
case 0: /* A-A Impossible */
case 2: /* A-C Impossible */
case 5: /* B-B Impossible */
case 7: /* B-D Impossible */
case 8: /* C-A Impossible */
case 10: /* C-C Impossible */
case 13: /* D-B impossible */
case 15: /* D-D Impossible */
break;
case 1: /* A-B */
LeftBDeltaX=lconvert(Texture->XSize,L_Size,65536);
LeftBDeltaY=0;
LeftXPos=0; LeftYPos=0;
break;
case 3: /* A-D */
LeftBDeltaY=lconvert(Texture->YSize,L_Size,65536);
LeftBDeltaX=0;
LeftXPos=0; LeftYPos=0;
break;
case 4: /* B-A */
LeftBDeltaX=-lconvert(Texture->XSize,L_Size,65536);
LeftBDeltaY=0;
LeftXPos=Texture->XSize-1; LeftYPos=0;
break;
case 6: /* B-C */
LeftBDeltaY=lconvert(Texture->YSize,L_Size,65536);
LeftBDeltaX=0;
LeftXPos=Texture->XSize-1; LeftYPos=0;
break;
case 9: /* C-B */
LeftBDeltaY=-lconvert(Texture->YSize,L_Size,65536);
LeftBDeltaX=0;
LeftXPos=Texture->XSize-1; LeftYPos=Texture->YSize-1;
break;
case 11: /* C-D */
LeftBDeltaX=-lconvert(Texture->XSize,L_Size,65536);
LeftBDeltaY=0;
LeftXPos=Texture->XSize-1; LeftYPos=Texture->YSize-1;
break;
case 12: /* D-A */
LeftBDeltaY=-lconvert(Texture->YSize,L_Size,65536);
LeftBDeltaX=0;
LeftXPos=0; LeftYPos=Texture->YSize-1;
break;
case 14: /* D-C */
LeftBDeltaX=lconvert(Texture->XSize,L_Size,65536);
LeftBDeltaY=0;
LeftXPos=0; LeftYPos=Texture->YSize-1;
break;
}
switch((RightVectorA<<2)|RightVectorB)
{
case 0: /* A-A Impossible */
case 2: /* A-C Impossible */
case 5: /* B-B Impossible */
case 7: /* B-D Impossible */
case 8: /* C-A Impossible */
case 10: /* C-C Impossible */
case 13: /* D-B impossible */
case 15: /* D-D Impossible */
break;
case 1: /* A-B */
RightBDeltaX=lconvert(Texture->XSize,R_Size,65536);
RightBDeltaY=0;
RightXPos=0; RightYPos=0;
break;
case 3: /* A-D */
RightBDeltaY=lconvert(Texture->YSize,R_Size,65536);
RightBDeltaX=0;
RightXPos=0; RightYPos=0;
break;
case 4: /* B-A */
RightBDeltaX=-lconvert(Texture->XSize,R_Size,65536);
RightBDeltaY=0;
RightXPos=Texture->XSize-1; RightYPos=0;
break;
case 6: /* B-C */
RightBDeltaY=lconvert(Texture->YSize,R_Size,65536);
RightBDeltaX=0;
RightXPos=Texture->XSize-1; RightYPos=0;
break;
case 9: /* C-B */
RightBDeltaY=-lconvert(Texture->YSize,R_Size,65536);
RightBDeltaX=0;
RightXPos=Texture->XSize-1; RightYPos=Texture->YSize-1;
break;
case 11: /* C-D */
RightBDeltaX=-lconvert(Texture->XSize,R_Size,65536);
RightBDeltaY=0;
RightXPos=Texture->XSize-1; RightYPos=Texture->YSize-1;
break;
case 12: /* D-A */
RightBDeltaY=-lconvert(Texture->YSize,R_Size,65536);
RightBDeltaX=0;
RightXPos=0; RightYPos=Texture->YSize-1;
break;
case 14: /* D-C */
RightBDeltaX=lconvert(Texture->XSize,R_Size,65536);
RightBDeltaY=0;
RightXPos=0; RightYPos=Texture->YSize-1;
break;
}
LeftXPos*=65536; LeftYPos*=65536;
RightXPos*=65536; RightYPos*=65536;
lva[0]=LeftVectorA;
lvb[0]=LeftVectorB;
rva[0]=RightVectorA;
rvb[0]=RightVectorB;
lcnt[0]=LeftCount;
rcnt[0]=RightCount;
for(i=0;i<ysize;i++)
{
m=poly->y[Order[0]]+i;
if(m>199)
break;
if(!LeftCount)
{
/* Get next Left Vector */
j=LeftVectorB; k=(LeftVectorB+1)%4;
if(k==LeftVectorA)
{
k=(LeftVectorB+3)%4;
}
LeftVectorA=j; LeftVectorB=k;
LeftX=poly->x[LeftVectorA]*65536;
LeftCount=poly->y[LeftVectorB]-poly->y[LeftVectorA];
lva[lcount]=LeftVectorA;
lvb[lcount]=LeftVectorB;
lcnt[lcount]=LeftCount;
lcount++;
j=poly->x[LeftVectorB]-poly->x[LeftVectorA];
L_Size=LeftCount;
LeftDelta=lconvert(j,LeftCount,65536);
switch((LeftVectorA<<2)|LeftVectorB)
{
case 0: /* A-A Impossible */
case 2: /* A-C Impossible */
case 5: /* B-B Impossible */
case 7: /* B-D Impossible */
case 8: /* C-A Impossible */
case 10: /* C-C Impossible */
case 13: /* D-B impossible */
case 15: /* D-D Impossible */
break;
case 1: /* A-B */
LeftBDeltaX=lconvert(Texture->XSize,L_Size,65536);
LeftBDeltaY=0;
LeftXPos=0; LeftYPos=0;
break;
case 3: /* A-D */
LeftBDeltaY=lconvert(Texture->YSize,L_Size,65536);
LeftBDeltaX=0;
LeftXPos=0; LeftYPos=0;
break;
case 4: /* B-A */
LeftBDeltaX=-lconvert(Texture->XSize,L_Size,65536);
LeftBDeltaY=0;
LeftXPos=Texture->XSize-1; LeftYPos=0;
break;
case 6: /* B-C */
LeftBDeltaY=lconvert(Texture->YSize,L_Size,65536);
LeftBDeltaX=0;
LeftXPos=Texture->XSize-1; LeftYPos=0;
break;
case 9: /* C-B */
LeftBDeltaY=-lconvert(Texture->YSize,L_Size,65536);
LeftBDeltaX=0;
LeftXPos=Texture->XSize-1; LeftYPos=Texture->YSize-1;
break;
case 11: /* C-D */
LeftBDeltaX=-lconvert(Texture->XSize,L_Size,65536);
LeftBDeltaY=0;
LeftXPos=Texture->XSize-1; LeftYPos=Texture->YSize-1;
break;
case 12: /* D-A */
LeftBDeltaY=-lconvert(Texture->YSize,L_Size,65536);
LeftBDeltaX=0;
LeftXPos=0; LeftYPos=Texture->YSize-1;
break;
case 14: /* D-C */
LeftBDeltaX=lconvert(Texture->XSize,L_Size,65536);
LeftBDeltaY=0;
LeftXPos=0; LeftYPos=Texture->YSize-1;
break;
}
LeftXPos*=65536; LeftYPos*=65536;
}
if(!RightCount)
{
/* Get next Right Vector */
j=RightVectorB; k=(RightVectorB+1)%4;
if(k==RightVectorA)
{
k=(RightVectorB+3)%4;
}
RightVectorA=j; RightVectorB=k;
RightX=poly->x[RightVectorA]*65536;
RightCount=poly->y[RightVectorB]-poly->y[RightVectorA];
R_Size=RightCount;
rva[rcount]=RightVectorA;
rvb[rcount]=RightVectorB;
rcnt[rcount]=RightCount;
rcount++;
j=poly->x[RightVectorB]-poly->x[RightVectorA];
RightDelta=lconvert(j,RightCount,65536);
switch((RightVectorA<<2)|RightVectorB)
{
case 0: /* A-A Impossible */
case 2: /* A-C Impossible */
case 5: /* B-B Impossible */
case 7: /* B-D Impossible */
case 8: /* C-A Impossible */
case 10: /* C-C Impossible */
case 13: /* D-B impossible */
case 15: /* D-D Impossible */
break;
case 1: /* A-B */
RightBDeltaX=lconvert(Texture->XSize,R_Size,65536);
RightBDeltaY=0;
RightXPos=0; RightYPos=0;
break;
case 3: /* A-D */
RightBDeltaY=lconvert(Texture->YSize,R_Size,65536);
RightBDeltaX=0;
RightXPos=0; RightYPos=0;
break;
case 4: /* B-A */
RightBDeltaX=-lconvert(Texture->XSize,R_Size,65536);
RightBDeltaY=0;
RightXPos=Texture->XSize-1; RightYPos=0;
break;
case 6: /* B-C */
RightBDeltaY=lconvert(Texture->YSize,R_Size,65536);
RightBDeltaX=0;
RightXPos=Texture->XSize-1; RightYPos=0;
break;
case 9: /* C-B */
RightBDeltaY=-lconvert(Texture->YSize,R_Size,65536);
RightBDeltaX=0;
RightXPos=Texture->XSize-1; RightYPos=Texture->YSize-1;
break;
case 11: /* C-D */
RightBDeltaX=-lconvert(Texture->XSize,R_Size,65536);
RightBDeltaY=0;
RightXPos=Texture->XSize-1; RightYPos=Texture->YSize-1;
break;
case 12: /* D-A */
RightBDeltaY=-lconvert(Texture->YSize,R_Size,65536);
RightBDeltaX=0;
RightXPos=0; RightYPos=Texture->YSize-1;
break;
case 14: /* D-C */
RightBDeltaX=lconvert(Texture->XSize,R_Size,65536);
RightBDeltaY=0;
RightXPos=0; RightYPos=Texture->YSize-1;
break;
}
RightXPos*=65536; RightYPos*=65536;
}
/* Now, We can shoot our row... */
j=(LeftXPos/65536); j+=((LeftYPos/65536)*Texture->XSize);
/* j=offset into bitmap... */
k=(RightX-LeftX)/65536; /* Size of line... */
if(m<0) k=0; /* Skip if above screen */
m=LeftX/65536; n=RightX/65536;
if((n<0)||(m>319))
{
k=0; /* No line to be draw... */
}
if(k)
{
OSize=k;
p=LeftXPos; q=LeftYPos;
o=LeftX/65536;
if(m<0)
{
if((m+k)>0) /* Clip Left Boundary */
{
m=-m;
p+=(((RightXPos-LeftXPos)/k)*m);
q+=(((RightYPos-LeftYPos)/k)*m);
o+=m;
}
else
k=0;
}
if(n>319) /* Clip Right boundary */
{
n-=319;
k-=n;
}
}
/*
This is the "inner" loop. Clipping has already been done.
"p" is our fixed point bitmap X position
"q" is our fixed point bitmap Y position
"m" is our starting screen X position
*/
if(k>2)
{
m=(RightXPos-LeftXPos)/OSize; n=(RightYPos-LeftYPos)/OSize;
/* m and n equal deltas for bitmap ray */
if(debug)
{
if(getch()==' ')
{
GL_TextMode();
/* GrSetMode(GR_default_text); */
printf("XInc= %f YInc=%f OSize=%d",fixed2float(m),
fixed2float(n),OSize);
printf("ScreenPos=%d P=%f Q=%f\n",o,
fixed2float(p),fixed2float(q));
printf("LeftX=%f RightX=%f ",fixed2float(LeftXPos),
fixed2float(RightXPos));
printf("LeftY=%f RightY=%f ",fixed2float(LeftYPos),
fixed2float(RightYPos));
printf("(%c-%c)/(%c-%c)\n",
LeftVectorA+'A',LeftVectorB+'A',RightVectorA+'A',
RightVectorB+'A');
printf(
"L_Size=%d R_Size=%d LeftCount=%d RightCount=%d\n",
L_Size,R_Size,LeftCount,RightCount);
printf("A(%d,%d) B(%d,%d) C(%d,%d) D(%d,%d)\n",
poly->x[0],poly->y[0],poly->x[1],poly->y[1],
poly->x[2],poly->y[2],poly->x[3],poly->y[3]);
exit(0);
}
}
for(;k;k--,o++)
{
j=(p/65536); j+=((q/65536)*Texture->XSize);
screenptr[o]=Texture->Buffer[j];
p+=m; q+=n;
}
}
/* Ending position in bitmap... */
LeftCount--; RightCount--;
RightXPos+=RightBDeltaX;
RightYPos+=RightBDeltaY;
LeftXPos+=LeftBDeltaX;
LeftYPos+=LeftBDeltaY;
LeftX+=LeftDelta;
RightX+=RightDelta;
screenptr+=320;
}
}